package com.flc.gateway.utils;


import java.io.ByteArrayOutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;

/**
 * 字节数组处理工具
 * @author HaiziGe
 * @date 2018/1/2
 */
public class ByteUtils {

    private static final char[] HEX_CHAR = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
    private static final String HEX_STRING = "0123456789ABCDEF";


     /* ------------- byte[] -> 基本数据类型 ---------------- */

    /**  byte[]转char  */
    public static char getChar8(byte[] bytes) {
        return (char) (0xff & bytes[0]);
    }

    /**  byte[]转char  */
    public static char getChar16(byte[] bytes) {
        return (char) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    /**  byte[]转short  */
    public static short getShort8(byte[] bytes) {
        return (short) (0xff & bytes[0]);
    }

    /**  byte[]转short  */
    public static short getShort16(byte[] bytes) {
        return (short) ((0xff00 & (bytes[0]<<8)) | (0xff & bytes[1]));
        // return (short) ((0xff & bytes[0]) | (0xff00 & (bytes[1] << 8)));
    }

    /**  byte[]转int -8位 */
    public static int getInt8(byte[] bytes) {
        return (0xff & bytes[0]);
    }

    /**  byte[]转int -16位 */
    public static int getInt16(byte[] bytes) {
        return (bytes[0] << 8) | (bytes[1] & 0xff);
    }

    /**  byte[]转int -32位 */
    public static int getInt32(byte[] bytes) {
        return bytes[0] << 24
                | (bytes[1] & 0xff) << 16
                | (bytes[2] & 0xff) << 8
                | (bytes[3] & 0xff);
    }

    /**  byte[]转int -32位 */
    public static int getInt323232(byte[] bytes) {
        return (0xff000000 & (bytes[0]<<24))
                | (0xff0000 & (bytes[1]<<16))
                | (0xff00 & (bytes[2]<<8))
                | (0xff & bytes[3]);
    }

    /**  byte[]转int -32位 */
    public static int getInt3232(byte[] bytes) {
        int mask=0xff;
        int temp=0;
        int n=0;
        for(int i=0;i<bytes.length;i++){
            n<<=8;
            temp=bytes[i]&mask;
            n|=temp;
        }
        return n;
    }

    /**  byte[]转long -32位 */
    public static long getLong32(byte[] bytes) {
        return 0x0ffffffffL & (bytes[0] << 24
                | (bytes[1] & 0xff) << 16
                | (bytes[2] & 0xff) << 8
                | (bytes[3] & 0xff));
    }

    /**  byte[]转long -64位 */
    public static long getLong64(byte[] bytes) {
        return (long) bytes[0] << 54
                | (long) (bytes[1] & 0xff) << 48
                | (long) (bytes[2] & 0xff) << 40
                | (long) (bytes[3] & 0xff) << 32
                | (long) (bytes[4] & 0xff) << 24
                | (long) (bytes[5] & 0xff) << 16
                | (long) (bytes[6] & 0xff) << 8
                | (long) (bytes[7] & 0xff);
    }

    /**  byte[]转float  */
    public static float getFloat(byte[] bytes) {
        return Float.intBitsToFloat(getInt32(bytes));
    }

    /**  byte[]转double  */
    public static double getDouble(byte[] bytes) {
        return Double.longBitsToDouble(getLong64(bytes));
    }

    /**  byte[]转String 默认编码utf8  */
    public static String getString(byte[] bytes) {
        return getString(bytes, "UTF-8");
    }

    /**  byte[]转String 指定编码  */
    public static String getString(byte[] bytes, String charsetName) {
        return new String(bytes, Charset.forName(charsetName));
    }

    /**  byte[]转十六进制String  */
    public static String getHexString(byte[] bytes) {
        char[] buf = new char[bytes.length * 2];
        int index = 0;
        for(byte b : bytes) {
            buf[index++] = HEX_CHAR[b >>> 4 & 0xf];
            buf[index++] = HEX_CHAR[b & 0xf];
        }
        return new String(buf);
    }

    /**  byte[]转char  */
    public static char getChar8WithIndex(byte[] bytes, int index) {
        return (char) (0xff & bytes[index]);
    }

    /**  byte[]转char  */
    public static char getChar16WithIndex(byte[] bytes, int index) {
        return (char) ((0xff & bytes[index]) | (0xff00 & (bytes[index+1] << 8)));
    }

    /**  byte[]转short  */
    public static short getShort8WithIndex(byte[] bytes, int index) {
        return (short) (0xff & bytes[index]);
    }

    /**  byte[]转short  */
    public static short getShort16WithIndex(byte[] bytes, int index) {
        return (short) ((0xff00 & (bytes[index]<<8)) | (0xff & bytes[index+1]));
    }

    /**  byte[]转int -8位 */
    public static int getInt8WithIndex(byte[] bytes, int index) {
        return (0xff & bytes[index]);
    }

    /**  byte[]转int -16位 */
    public static int getInt16WithIndex(byte[] bytes, int index) {
        return (bytes[index] << 8) | (bytes[index+1] & 0xff);
    }

    /**  byte[]转int -32位 */
    public static int getInt32WithIndex(byte[] bytes, int index) {
        return bytes[index] << 24
                | (bytes[index+1] & 0xff) << 16
                | (bytes[index+2] & 0xff) << 8
                | (bytes[index+3] & 0xff);
    }

    /**  byte[]转long -32位 */
    public static long getLong32WithIndex(byte[] bytes, int index) {
        return 0x0ffffffffL & (bytes[index] << 24
                | (bytes[index+1] & 0xff) << 16
                | (bytes[index+2] & 0xff) << 8
                | (bytes[index+3] & 0xff));
    }

    /**  byte[]转long -64位 */
    public static long getLong64WithIndex(byte[] bytes, int index) {
        return (long) bytes[index] << 54
                | (long) (bytes[index+1] & 0xff) << 48
                | (long) (bytes[index+2] & 0xff) << 40
                | (long) (bytes[index+3] & 0xff) << 32
                | (long) (bytes[index+4] & 0xff) << 24
                | (long) (bytes[index+5] & 0xff) << 16
                | (long) (bytes[index+6] & 0xff) << 8
                | (long) (bytes[index+7] & 0xff);
    }

    /**  byte[]转float  */
    public static float getFloatWithIndex(byte[] bytes, int index) {
        return Float.intBitsToFloat(getInt32WithIndex(bytes, index));
    }

    /**  byte[]转double  */
    public static double getDoubleWithIndex(byte[] bytes, int index) {
        return Double.longBitsToDouble(getLong64WithIndex(bytes, index));
    }

    /**  byte[]转String 默认编码utf8  */
    public static String getStringWithIndex(byte[] bytes, int index, int length) {
        return getStringWithIndex(bytes, index, length, "UTF-8");
    }

    /**  byte[]转String 指定编码  */
    public static String getStringWithIndex(byte[] bytes, int index, int length, String charsetName) {
        return new String(bytes, index, length, Charset.forName(charsetName));
    }

    /**  byte[]转十六进制String  */
    public static String getHexStringWithIndex(byte[] bytes, int index, int length) {
        char[] buf = new char[length * 2];
        for (int i = 0; i < length; ) {
            buf[i] = HEX_CHAR[bytes[index+i] >>> 4 & 0xf];
            i++;
            buf[i] = HEX_CHAR[bytes[index+i] & 0xf];
            i++;
        }
        return new String(buf);
    }


    /* ---------------- 基本数据类型 -> byte[] ---------------- */

    /**  char转byte[]  */
    public static byte[] charToBytes(char data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (data);
        bytes[1] = (byte) (data >> 8);
        return bytes;
    }

    /**  short转byte[]  */
    public static byte[] shortToBytes(short data) {
        byte[] bytes = new byte[2];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        return bytes;
    }

    /**  int转byte[]  */
    public static byte[] intToBytes(int data) {
        byte[] bytes = new byte[4];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data & 0xff00) >> 8);
        bytes[2] = (byte) ((data & 0xff0000) >> 16);
        bytes[3] = (byte) ((data & 0xff000000) >> 24);
        return bytes;
    }

    /**  long转byte[]  */
    public static byte[] longToBytes(long data) {
        byte[] bytes = new byte[8];
        bytes[0] = (byte) (data & 0xff);
        bytes[1] = (byte) ((data >> 8) & 0xff);
        bytes[2] = (byte) ((data >> 16) & 0xff);
        bytes[3] = (byte) ((data >> 24) & 0xff);
        bytes[4] = (byte) ((data >> 32) & 0xff);
        bytes[5] = (byte) ((data >> 40) & 0xff);
        bytes[6] = (byte) ((data >> 48) & 0xff);
        bytes[7] = (byte) ((data >> 56) & 0xff);
        return bytes;
    }

    /**  float转byte[]  */
    public static byte[] floatToBytes(float data) {
        int intBits = Float.floatToIntBits(data);
        return intToBytes(intBits);
    }

    /**  double转byte[]  */
    public static byte[] doubleToBytes(double data) {
        long longBits = Double.doubleToLongBits(data);
        return longToBytes(longBits);
    }

    /**  string转byte[] 默认编码 UTF-8  */
    public static byte[] stringToBytes(String data) {
        return stringToBytes(data, "UTF-8");
    }

    /**  string转byte[] 指定编码  */
    public static byte[] stringToBytes(String data, String charsetName) {
        Charset charset = Charset.forName(charsetName);
        return data.getBytes(charset);
    }

    /**  十六进制String转byte[] */
    public static byte[] hexStringToBytes(String hexString)
    {
        ByteArrayOutputStream baos=new ByteArrayOutputStream(hexString.length()/2);
        for(int i=0;i<hexString.length();i+=2){
            baos.write((HEX_STRING.indexOf(hexString.charAt(i))<<4 |HEX_STRING.indexOf(hexString.charAt(i+1))));
        }
        return baos.toByteArray();
    }

    public static void main(String[] args) throws UnsupportedEncodingException {

        byte[] bytes = new byte[4];
        bytes[0] = 0x00;
        bytes[1] = 0x01;
        bytes[2] = 0x01;
        bytes[3] = 0x01;


        for (byte b : bytes) {
            System.out.println(b);
        }
        String hexString = getHexString(bytes);
        System.out.println(hexString);
        System.out.println(getInt32(bytes));

        String hexStringTest = "01110131323334353637383132333435363738395A4D842C01F431333531323334353637380000000019000A0041D0A3D742EEAAAA012C012CFFAE9867540001000000000C06";
        bytes = hexStringToBytes(hexStringTest);
        for (byte b : bytes) {
            System.out.println(b);
        }
        System.out.println(getShort8WithIndex(bytes, 0));
        System.out.println(getShort8WithIndex(bytes, 1));
        System.out.println(getShort8WithIndex(bytes, 2));
        System.out.println(getStringWithIndex(bytes, 3, 17));
        System.out.println(getLong32WithIndex(bytes, 20));
        System.out.println(getShort16WithIndex(bytes, 24));
        System.out.println(getString(subBytes(bytes, 26, 15)));
        System.out.println(getShort8(subBytes(bytes, 41, 1)));
        System.out.println(getShort8(subBytes(bytes, 42, 1)));
        System.out.println(getShort8(subBytes(bytes, 43, 1)));
        System.out.println(getShort8(subBytes(bytes, 44, 1)));
        System.out.println(getFloat(subBytes(bytes, 45, 4)));
        System.out.println(getFloat(subBytes(bytes, 49, 4)));
        System.out.println(getShort16(subBytes(bytes, 53, 2)));
        System.out.println(getShort16(subBytes(bytes, 55, 2)));
        System.out.println(getShort8(subBytes(bytes, 57, 1)));
        System.out.println(getLong32(subBytes(bytes, 58, 4)));
        System.out.println(getShort16(subBytes(bytes, 62, 2)));
        System.out.println(getShort16(subBytes(bytes, 64, 2)));
        System.out.println(getShort16(subBytes(bytes, 66, 2)));
        System.out.println(getShort8(subBytes(bytes, 68, 1)) +
                getShort8(subBytes(bytes, 69, 1)) * 0.1f);

    }

    public static byte[] subBytes(byte[] src, int startIndex, int length) {
        byte[] dest = new byte[length];
        System.arraycopy(src, startIndex, dest, 0, length);
        return dest;

    }


}